using System;
using System.IO;
using System.Web;
using System.Drawing;
using System.Collections;
using System.Text;

namespace com.flajaxian
{
    /// <summary>
    /// This adapter can be used to create thumbnails for the image files.
    /// </summary>
    public class ThumbGeneratorAdapter : FileUploaderAdapter
    {
        private string[] _extensionsArray;
        private string _extensions;
        private string _folderName = "/";
        private int _maximumWidth = 50;
        private int _maximumHeight = 50;
        private string _prefix = String.Empty;
        private string _suffix = String.Empty;

        public event EventHandler<FileNameDeterminingEventArgs> FileNameDetermining;

        /// <summary>
        /// Constructor with no arguments.
        /// </summary>
        public ThumbGeneratorAdapter()
        {
            this.Extensions = Constants.DefaultImageExtensions;
        }

        /// <summary>
        /// Creating thumbnail for an image file on the server. Each file triggers a separate call of this method.
        /// </summary>
        /// <param name="file">Incoming file</param>
        public override void ProcessFile(HttpPostedFile file)
        {
            this.GenerateThumbnail(
                file,
                this.Parent.Page.Server.MapPath(this.FolderName),
                this.MaximumWidth,
                this.MaximumHeight
            );
        }

        
        /// <summary>
        /// A list of allowed file extensions that will be used as a model for the thumbnails.
        /// You can use on of the following separators ;,| for example Extensions="jpg;jpeg"
        /// </summary>
        public string Extensions
        {
            get { return this._extensions; }
            set 
            {
                this._extensions = value;
                this._extensionsArray = this._extensions.Split(";,|".ToCharArray());
                for (int i = 0; i < this._extensionsArray.Length; i++)
                {
                    this._extensionsArray[i] = this._extensionsArray[i].ToLower();
                }
            }
        }

        /// <summary>
        /// The name of the folder where you would like to upload the thumbnails.
        /// </summary>
        public string FolderName
        {
            get { return this._folderName; }
            set { this._folderName = value; }
        }

        /// <summary>
        /// Maximum size of the width of the generated templates.
        /// </summary>
        public int MaximumWidth
        {
            get { return this._maximumWidth; }
            set { this._maximumWidth = value; }
        }

        /// <summary>
        /// Maximum size of the height of the generated templates.
        /// </summary>
        public int MaximumHeight
        {
            get { return this._maximumHeight; }
            set { this._maximumHeight = value; }
        }

        /// <summary>
        /// Prefix of the generated templates, by default is an empty string.
        /// </summary>
        public string Prefix
        {
            get { return this._prefix; }
            set { this._prefix = value; }
        }

        /// <summary>
        /// Suffix of the generated templates, by default is an empty string.
        /// </summary>
        public string Suffix
        {
            get { return this._suffix; }
            set { this._suffix = value; }
        }

        private static string RemoveDot(string ext)
        {
            if (String.IsNullOrEmpty(ext))
            {
                return ext;
            }
            if (ext.StartsWith("."))
            {
                ext = ext.Substring(1); 
            }
            return ext;
        }


        private bool GenerateThumbnail(HttpPostedFile file, string thumbnailPath, int maxWidth, int maxHeight)
        {
            Stream stream = file.InputStream;
            string thumbnailFileName = file.FileName;

            int extIndex = Array.IndexOf(this._extensionsArray, RemoveDot(Path.GetExtension(thumbnailFileName.ToLower())));
            if (extIndex < 0)
            {
                return false;
            }

            thumbnailPath = Path.GetFullPath(thumbnailPath);

            Image image = Image.FromStream(stream);

            double ratio = image.Width / (double)image.Height;
            int width;
            int height;
            if (image.Width >= image.Height)
            {
                width = maxWidth;
                height = (int)Math.Round(width / ratio);
            }
            else
            {
                height = maxHeight;
                width = (int)Math.Round(height * ratio);
            }

            try
            {
                Image thumbnailImage =
                    image.GetThumbnailImage(width, height, new Image.GetThumbnailImageAbort(delegate { return true; }), IntPtr.Zero);


                string fileName = String.Concat(
                        thumbnailPath,
                        Path.DirectorySeparatorChar,
                        this.Prefix,
                        Path.GetFileNameWithoutExtension(thumbnailFileName),
                        this.Suffix,
                        Path.GetExtension(thumbnailFileName)
                    );


                fileName = this.OnFileNameDetermining(file, fileName);

                if(fileName != null)
                {
                    thumbnailImage.Save(fileName);
                }

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        protected virtual string OnFileNameDetermining(HttpPostedFile file, string fileName)
        {
            if (this.FileNameDetermining != null)
            {
                FileNameDeterminingEventArgs args = new FileNameDeterminingEventArgs(file);

                args.FileName = fileName;

                this.FileNameDetermining(this, args);

                if(args.CancelProcessing)
                {
                    return null;
                }

                return args.FileName;
            }
            return fileName;
        }
    }
}
